-module(storage).
-export([create_proc/0,create_test_user/1]).

%% NOTE: This requires you to have emysql 
%% installed in the erlang lib folder

%% Eshell V5.8  (abort with ^G)
%% 1> DB = storage:create_proc().
%% Starting storage process
%% <0.48.0>
%% 2> User = storage:create_test_user(DB).
%% Creating test user!
%% <0.50.0>
%% 3> User ! {put,{"morot","hund"}}.
%% OK
%% 4> User ! {get,"morot"}.
%% printing the content
%% 5> User ! {remove, "morot"}.
%% OK, morot remove
%% 5> User ! {remove, "morot"}.
%% OK, morot removed

create_proc() ->
   io:fwrite("Starting storage process\n"),
   crypto:start(),
   application:start(emysql),
   %% Creating a pool...
   %% poolname, members in pool???, mysql user,
   %% mysql password, host, port, database name,
   %% text encoding
   emysql:add_pool(pool, 1, "root", "",
      "192.168.1.100", 3306, "main", utf8),
   spawn(fun() -> listen() end).

listen() ->
   receive
      %% Get the value from backend
      %% @get=atom, SenderProc=process, Key=str
      {get,SenderProc,Key}
         ->
            io:fwrite("query backend database"),
            Res = emysql:execute(pool,list_to_binary("SELECT value FROM map where id='"++Key++"';")),
            SenderProc ! {get_result,Res},
            listen();
      %% Store the key and value to backend
      {put,{Key,Value}}
         ->
            io:fwrite("store to backend"),
            emysql:execute(pool,
                           list_to_binary("INSERT INTO map VALUES('"++Key++"','"++Value++"');")),
            listen();
      {remove,Key}
         ->
            io:fwrite("remove from backend"),
            emysql:execute(pool,
                           list_to_binary("DELETE FROM map WHERE id = '"++Key++"';")),
            listen()
   end.


create_test_user(StorageProc) ->
   io:fwrite("Creating test user!\n"),
   spawn(fun() -> test_user(StorageProc) end).

test_user(StorageProc) ->
   receive
      %% Test user receiving a get from user
      {get,Key} ->
         io:fwrite("User about to do get\n"),
         StorageProc ! {get,self(),Key},
         test_user(StorageProc);
      %% Test user receiving a put from user
      {put,{Key,Value}} ->
         io:fwrite("User about to do put\n"),
         StorageProc ! {put,{Key,Value}},
         test_user(StorageProc);
      %% Test user receiving a result from storage process
      {remove,Key} ->
         StorageProc ! {remove,Key},
         test_user(StorageProc);
      {get_result,Res} ->
         io:fwrite("Printing result from DB:\n"),
         io:format("~n~p~n", [Res]),
         test_user(StorageProc)
   end.
